package org.jeecg.modules.cascv.image.util;

import cn.hutool.core.util.HexUtil;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by Niler on 17/5/18.
 */
public class NumberUtil {
    private static final int INTEGERMASK = -1;

    //高前低后 补码
    public static int byte2UnsignedByte(byte[] bytes, int off) {
        return bytes[off] & 0xFF;
    }

    public static int byte2UnsignedByte(byte[] bytes, int off, int from, int to) {
        //因为short和byte计算时,一定会被升为int,所以用int来计算
        int temp = bytes[off];
        temp >>>= to;
        temp &= (INTEGERMASK >>> (31 - from + to));//32-(from-to+1)
        return temp;
    }

    public static String bytes2HexStr(byte[] bytes){
        return bytes2HexStr(bytes, 0, bytes.length);
    }

    public static String bytes2HexStr(byte[] bytes, int from, int to){
        int i = from < 0 ? 0 : from;
        int size = bytes.length;
        int len = to > size ? size: to;
        StringBuffer buffer = new StringBuffer(len - i);
        String temp;
        for(; i < len; i++) {
            byte b = bytes[i];
            temp = Integer.toHexString(0xFF & b);
            if(temp.length() < 2){
                buffer.append(0);
            }
            buffer.append(temp);
        }
        return buffer.toString();
    }

    public static byte[] hexStr2bytes(String s){
        int len = s.length();
        byte[] b = new byte[len / 2];
        for(int i = 0; i < len; i+=2){
            b[i / 2] = (byte) ( (Character.digit(s.charAt(i),16) <<4) +Character.digit(s.charAt(i + 1),16) );
        }
        return b;
    }
    public static int byte2Byte(byte[] bytes, int off) {
        return bytes[off];
    }

    public static int byte2UnsignedShort(byte[] bytes, int off) {
        return (bytes[off] & 0xFF) << 8 | bytes[off + 1] & 0xFF;
    }
    public static int byte2UnsignedShort(byte[] bytes, int off, int from, int to) {
        if(from<8){
            return byte2UnsignedByte(bytes,off+1,from,to);
        }
        else if(to>=8){
            return byte2UnsignedByte(bytes,off,from-8,to-8);
        }
        else{
            int byte1 = bytes[off + 1]>>>to;
            byte1 &= (INTEGERMASK >>> (24 + to));//32-(7-to+1)
            int byte0 = bytes[off]&(INTEGERMASK >>> (39 - from));//32-(from-8+1)
            byte0<<=8-to;
            byte1|=byte0;
            return byte1;

        }
    }


    public static int byte2Short(byte[] bytes, int off) {
        return bytes[off] << 8 | bytes[off + 1] & 0xFF;
    }

    public static int versbyte2Short(byte[] bytes, int off){
        return bytes[off+1] << 8 | bytes[off] & 0xFF;
    }

    public static long byte2UnsignedInteger(byte[] bytes, int off) {
        long value = 0;
        for(int i=off; i<bytes.length; i++){
            value |= (long) (bytes[i] & 0xFF) << ((bytes.length-1)*8 - i*8);
        }
        return value;
    }

    public static int byte2UnsignedInteger(byte[] bytes, int from, int to) {
        int[] byteInt=new int[4];
        for(int i=0;i<4&&from>=to;i++){
            int startOfByte=(3-i)*8;
            if(from>=startOfByte)
            {
                if(to>=startOfByte) {
                    byteInt[i] = byte2UnsignedByte(bytes, i, from - startOfByte, to - startOfByte);
                    break;
                }
                else {
                    byteInt[i] = byte2UnsignedByte(bytes, i, from - startOfByte, 0);
                    byteInt[i]<<=startOfByte-to;
                }
                from=startOfByte-1;

            }

        }
        return byteInt[0]|byteInt[1]|byteInt[2]|byteInt[3];
    }

    private static long byte2Long(byte[] bytes, int off) {
        long value = 0;
        for (int i = 0; i < 8; i++) {
            value |= ((long) (bytes[i + off] & 0xff)) << (56 - 8 * i);
        }
        return value;
    }

    public static int byte2Integer(byte[] bytes, int off) {
        return bytes[off] << 24 | (bytes[off + 1] & 0xFF) << 16 | (bytes[off + 2] & 0xFF) << 8 | bytes[off + 3] & 0xFF;
    }

    public static int versbyte22Integer(byte[] bytes, int off){
        return (bytes[off + 1] & 0xFF) << 8 | bytes[off] & 0xFF;
    }

    public static int versbyte3Integer(byte[] bytes, int off){
        return bytes[off+2] << 16 | (bytes[off + 1] & 0xFF) << 8 | bytes[off] & 0xFF;
    }

    public static int versbyte2Integer(byte[] bytes, int off){
        return bytes[off+3] << 24 | (bytes[off + 2] & 0xFF) << 16 | (bytes[off + 1] & 0xFF) << 8 | bytes[off] & 0xFF;
    }

    public static float byte2Float(byte[] bytes, int off) {
        int intBits = byte2Integer(bytes, off);
        return Float.intBitsToFloat(intBits);

//        ByteBuffer buf=ByteBuffer.allocateDirect(4); //无额外内存的直接缓存
//        //buf=buf.order(ByteOrder.LITTLE_ENDIAN);//默认大端，小端用这行
//        buf.put(bytes,off,4);
//        buf.rewind();
//        float f2=buf.getFloat();
    }

    public static double byte2Double(byte[] bytes, int off) {
        long value = byte2Long(bytes, off);
        return Double.longBitsToDouble(value);

    }

//    static {
//        ByteOrder byteOrder;
//        Field f = null;
//        Unsafe unsafe = null;
//        try {
//            f = Unsafe.class.getDeclaredField("theUnsafe");
//            f.setAccessible(true);
//            unsafe = (Unsafe) f.get(null);
//        } catch (NoSuchFieldException e) {
//            e.printStackTrace();
//        } catch (IllegalAccessException e) {
//            e.printStackTrace();
//        }
//        long a = unsafe.allocateMemory(8);
//        try {
//            unsafe.putLong(a, 0x0102030405060708L);
//            byte b = unsafe.getByte(a);
//            switch (b) {
//                case 0x01:
//                    byteOrder = ByteOrder.BIG_ENDIAN;
//                    break;
//                case 0x08:
//                    byteOrder = ByteOrder.LITTLE_ENDIAN;
//                    break;
//                default:
//                    assert false;
//                    byteOrder = null;
//            }
//        } finally {
//            unsafe.freeMemory(a);
//        }
//    }


    //目前认为只有字节之间的高低之分,字节内的bit没有高低之分
    public static void reverseByte(byte[] bytes, int start, int len) {
        int end = start + len - 1;
        while (start < end) {
            byte temp = bytes[start];
            bytes[start] = bytes[end];
            bytes[end] = temp;
            start++;
            end--;
        }
    }

    //对原码或者反码取补码
//    public static void toComplement(byte[] bytes, String encodingType) {
//        switch (encodingType) {
//            case Parameters.ENCODETYPE_ORIGINAL:{
//                NumberUtil.toComplement(bytes, true);}
//            break;
//            case Parameters.ENCODETYPE_ONESCOMPLEMENT:{
//                NumberUtil.toComplement(bytes, false);}
//        }
//
//    }

    private static void toComplement(byte[] bytes, boolean isOriginal) {
        if ((bytes[0] & 0x80) > 0) {
            if (isOriginal){
                flip(bytes);
            }
            plusOne(bytes);
        }

    }

    //取反码
    public static void flip(byte[] bytes) {
        bytes[0] ^= 127;
        for (int i = 1; i < bytes.length; i++) {
            bytes[i] ^= -1;
        }
    }

    public static void plusOne(byte[] bytes) {
        int last = 1;
        for (int i = bytes.length - 1; i >= 0; i--) {
            int temp = byte2UnsignedByte(bytes, i) + last;
            last = (temp & 256) > 0 ? 1 : 0;
            bytes[i] = (byte) temp;
            if (last == 0){
                break;
            }
        }
    }

//    public static int getBitFromBytes(byte[] bytes,int off,int from ,int to, String dataType){
//        switch (dataType){
//            case Parameters.DATATYPE_USIGNED_BYTE: {return byte2UnsignedByte(bytes,off,from,to);}
//            case Parameters.DATATYPE_USIGNED_SHORT: {return  byte2UnsignedShort(bytes,off,from,to);}
//            case Parameters.DATATYPE_USIGNED_INT: {return byte2UnsignedInteger(bytes,from,to);}
//        }
//        return -1;
//    }
    public static byte[] int2Byte(int n){
        byte[] b = new byte[4];
        for(int i=0; i<4; i++){
            b[i] = (byte)(n>>(24-i*8));
        }
        return b;
    }
    public static byte[] short2Byte(short s){

        byte[] b = new byte[2];
        for(int i=0; i<2; i++){
            int offset = 16-(i+1)*8;
            b[i] = (byte)( (s>>offset) & 0xff);
        }
        return b;
    }

    public static byte[] long2bytes(long num) {
        byte[] byteNum = new byte[8];
        for (int i = 0; i < 8; i++) {
            int offset = 64 - (i + 1) * 8;
            byteNum[i] = (byte) ((num >> offset) & 0xFF);
        }
        return byteNum;
    }

    public static Long converTimeToLong(String time){
        Date date = null;
        try{
            //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss.hhh.uuu");
            //SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss");
            date = sdf.parse(time);
            return date.getTime();
        } catch (Exception e){
            e.printStackTrace();
            return 0L;
        }
    }

    public static void main(String[] args){
        String imageSizeStr = "d15b0100";
        System.out.println(NumberUtil.versbyte2Integer(HexUtil.decodeHex(imageSizeStr), 0));
    }

}